'use server';

import ai from '@/lib/ai';
import { getSession } from '@/lib/auth';
import { db } from '@/lib/db';
import redis, {
  genInChatKey,
  genMessageKey,
  genNewMessageButNotInChatKey,
  genNewMessageNotOnlineKey,
} from '@/lib/redis';
import { checkOnline, sendSocketData } from '@/lib/socket';
import { result, withZod } from '@/lib/utils';
import { z } from 'zod';
import { BizError, ErrorCode } from '../error';
import { MESSAGE_EVENT, type Message } from '../type/socket';

export const sendMessage = withZod(
  z.object({
    toId: z.string(),
    content: z.string(),
  }),
  async ({ toId, content }) => {
    try {
      const session = await getSession();
      if (!session?.user)
        throw new BizError(ErrorCode.Unauthorized, '用户未登录');

      if (session.user.id === toId)
        throw new BizError(ErrorCode.BadRequest, '不能给自己发消息');

      const toUser = await db.query.user.findFirst({
        columns: {
          role: true,
        },
        where: (user, { eq }) => eq(user.id, toId),
      });
      if (!toUser) throw new BizError(ErrorCode.NotFound, '接受消息用户不存在');

      if (toUser.role === session.user.role)
        throw new BizError(ErrorCode.BadRequest, '发送消息对象错误');

      const shopData =
        session.user.role === 'shop'
          ? await db.query.shop.findFirst({
              columns: {
                name: true,
                imageKeys: true,
              },
              where: (shop, { eq }) => eq(shop.userId, session.user.id),
            })
          : null;

      const newMessage: Message = {
        user: {
          id: session.user.id,
          name:
            session.user.role === 'shop'
              ? (shopData?.name ?? session.user.name)
              : session.user.name,
          image:
            session.user.role === 'shop'
              ? (shopData?.imageKeys[0] ?? session.user.image)
              : session.user.image,
          role: session.user.role,
        },
        content,
        createdAt: new Date().getTime(),
      };

      sendSocketData<Message>({
        toIds: [toId, session.user.id],
        event: MESSAGE_EVENT,
        data: newMessage,
      });

      session.user.role === 'user' &&
        (
          await redis.keys(
            genInChatKey({
              userId: session.user.id,
              shopUserId: toId,
            }),
          )
        ).length === 0 &&
        redis.set(
          genNewMessageButNotInChatKey({
            userId: session.user.id,
            shopUserId: toId,
          }),
          '',
        );

      const isToUserOnline = await checkOnline(toId);
      !isToUserOnline &&
        redis.setEx(
          genNewMessageNotOnlineKey(toId),
          60 * 60 * 24,
          session.user.id,
        );

      const userId = session.user.role === 'user' ? session.user.id : toId;
      const messageKey = genMessageKey({
        userId,
        shopUserId: userId === toId ? session.user.id : toId,
      });
      const messagesJSON = await redis.get(messageKey);
      const messages = JSON.parse(messagesJSON || '[]') as Message[];
      messages.push(newMessage);
      await redis.setEx(messageKey, 60 * 60 * 24, JSON.stringify(messages));

      return result();
    } catch (error) {
      return result(error, '发送消息失败,请重试');
    }
  },
);

export const messagesAiSummary = async ({
  messages,
  redisKeyToDelete,
}: { messages: Message[]; redisKeyToDelete?: string }) => {
  try {
    const text = await ai.genText([
      {
        role: 'system',
        content:
          '现在这里是一个外卖系统的在线客服聊天界面，商铺需要对用户进行一些回答。商铺客服需要迅速了解用户的诉求，请根据以下的聊天记录总结用户的消息与诉求。150字以内。',
      },
      {
        role: 'user',
        content: messages
          .map(
            (m) =>
              `${m.user.role === 'user' ? '用户 - ' : '商铺 - '}${m.user.name} 说： ${m.content}`,
          )
          .join('\n'),
      },
    ]);
    redisKeyToDelete && redis.del(redisKeyToDelete);
    return result(text);
  } catch (error) {
    return result(error, '生成总结失败');
  }
};
